﻿using System;
using System.Web;
using log4net;
using Sherwood.Security;
using Sherwood.Web;

namespace Sherwood.Content.SearchServices
{
    public class SignedClientAuthenticator : ISearchServiceAuthenticator
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(SignedClientAuthenticator));
        
        private readonly IClientRepository _clientRepository;

        public SignedClientAuthenticator(IClientRepository clientRepository)
        {
            _clientRepository = clientRepository;
        }

        public virtual bool Authenticates(QueryParameterCollection queryString)
        {
            if(Log.IsDebugEnabled)
                Log.Debug("Authenticating " + queryString);

            QueryParameter signature;
            QueryParameter client;
            QueryParameter timestamp;
            if (!queryString.TryGetValue("signature", out signature) || 
                !queryString.TryGetValue("client", out client) ||
                !queryString.TryGetValue("timestamp", out timestamp))
            {
                if (Log.IsWarnEnabled)
                    Log.Warn("Client, signature or timestamp not specified");
                return false;
            }
            queryString.Remove(signature);

            string signedUrl = queryString.ToString();

            queryString.Remove(client);
            queryString.Remove(timestamp);
            
            if(Math.Abs(timestamp.ValueAsDate.Subtract(DateTime.UtcNow).TotalSeconds) > 300)
            {
                if (Log.IsWarnEnabled)
                    Log.Warn("Timestamp not within accepted timeframe");
                return false;
            }

            var rsa = Rsa.FromPublicKey(_clientRepository[client.Value].PublicKey);
            var authenticates = rsa.SHA1Verify(signedUrl, signature.Value);
            if(!authenticates && Log.IsDebugEnabled)
                Log.Debug(signedUrl + " does not match signature " + signature.Value);
            return authenticates;
        }
    }
}